

#define FMD_Init FMDHOOK_Init
#define FMD_GetInfo FMDHOOK_GetInfo
//#define FMD_GetInfoEx FMDHOOK_GetInfoEx
#define FMD_ReadSector FMDHOOK_ReadSector
#define FMD_WriteSector FMDHOOK_WriteSector

#define BLFMD_Init FMD_Init
#define BLFMD_Deinit FMD_Deinit
#define BLFMD_GetInfo FMD_GetInfo
#define BLFMD_GetBlockStatus FMD_GetBlockStatus
#define BLFMD_SetBlockStatus FMD_SetBlockStatus
#define BLFMD_ReadSector FMD_ReadSector
#define BLFMD_WriteSector FMD_WriteSector
#define BLFMD_EraseBlock FMD_EraseBlock
#define BLFMD_PowerUp FMD_PowerUp
#define BLFMD_PowerDown FMD_PowerDown
#define BLFMD_OEMIoControl FMD_OEMIoControl
#include "..\NANDFLASH\blFMD.cpp"
#include "..\NANDFLASH\BadBlockList.cpp"

#undef FMD_Init
#undef FMD_GetInfo
//#undef FMD_GetInfoEx
#undef FMD_ReadSector
#undef FMD_WriteSector

#ifdef __cplusplus
extern "C" {
#endif 

PVOID  FMD_Init(LPCTSTR lpActiveReg, PPCI_REG_INFO pRegIn, PPCI_REG_INFO pRegOut);
BOOL  FMD_GetInfo(PFlashInfo pFlashInfo);
BOOL  FMD_ReadSector (SECTOR_ADDR startSectorAddr, LPBYTE pSectorBuff, PSectorInfo pSectorInfoBuff, DWORD dwNumSectors);
BOOL  FMD_WriteSector(SECTOR_ADDR startSectorAddr, LPBYTE pSectorBuff, PSectorInfo pSectorInfoBuff, DWORD dwNumSectors);

#ifdef __cplusplus
}
#endif

// keep sync with fal!!!
#define CAP_SECT_SIG    (0x20706143)    // "Cap "

FlashInfo v_flashInfo;
#define MAX_SECTOR_SIZE	(4096)
BYTE v_CapBuf[MAX_SECTOR_SIZE];

PVOID  FMD_Init(LPCTSTR lpActiveReg, PPCI_REG_INFO pRegIn, PPCI_REG_INFO pRegOut)
{
	PVOID ret=FMDHOOK_Init(lpActiveReg, pRegIn, pRegOut);
	if( (!ret)
		|| (!FMDHOOK_GetInfo(&v_flashInfo)) )
	{
		return NULL;
	}

	ASSERT(MAX_SECTOR_SIZE>=v_flashInfo.wDataBytesPerSector);
	v_flashInfo.wSectorsPerBlock--;
	v_flashInfo.dwBytesPerBlock-=v_flashInfo.wDataBytesPerSector;
	DEBUGMSG(1, (TEXT("v_flashInfo dwNumBlocks:0x%x dwBytesPerBlock:0x%x, wSectorsPerBlock:0x%x, wDataBytesPerSector0x%x\r\n"), v_flashInfo.dwNumBlocks, v_flashInfo.dwBytesPerBlock, v_flashInfo.wSectorsPerBlock, v_flashInfo.wDataBytesPerSector));

	return ret;
}
BOOL  FMD_GetInfo(PFlashInfo pFlashInfo)
{
	*pFlashInfo=v_flashInfo;
	return TRUE;
}

BOOL  FMD_ReadSector (SECTOR_ADDR startSectorAddr, LPBYTE pSectorBuff, PSectorInfo pSectorInfoBuff, DWORD dwNumSectors)
{
	ASSERT(1==dwNumSectors);
	DWORD dwBlockId=startSectorAddr/v_flashInfo.wSectorsPerBlock;
	DWORD dwSectOffset=startSectorAddr%v_flashInfo.wSectorsPerBlock;
	startSectorAddr=dwBlockId*(v_flashInfo.wSectorsPerBlock+1)+dwSectOffset;

	return FMDHOOK_ReadSector(startSectorAddr, pSectorBuff, pSectorInfoBuff, dwNumSectors);
}

BOOL  FMD_WriteSector(SECTOR_ADDR startSectorAddr, LPBYTE pSectorBuff, PSectorInfo pSectorInfoBuff, DWORD dwNumSectors)
{
	ASSERT(1==dwNumSectors);
	DWORD dwBlockId=startSectorAddr/v_flashInfo.wSectorsPerBlock;
	DWORD dwSectOffset=startSectorAddr%v_flashInfo.wSectorsPerBlock;
	startSectorAddr=dwBlockId*(v_flashInfo.wSectorsPerBlock+1)+dwSectOffset;

	if(!FMDHOOK_WriteSector(startSectorAddr, pSectorBuff, pSectorInfoBuff, dwNumSectors))
	{
		return FALSE;
	}

	if( (dwSectOffset+1)==v_flashInfo.wSectorsPerBlock )
	{
	// auto cap
		PSectorInfo psectorInfoS=(PSectorInfo)&v_CapBuf;

        // read from data sectors
        startSectorAddr-=dwSectOffset;
		for(DWORD i=0; i<v_flashInfo.wSectorsPerBlock; i++, startSectorAddr++)
		{
			if(! FMDHOOK_ReadSector(startSectorAddr, NULL, psectorInfoS+i, 1))
			{
                DEBUGMSG(1, (TEXT("!!! ReadSector:0x%x for cap Error !!!\r\n"), startSectorAddr));
				return FALSE;
			}
		}

		SectorInfo si;
		memset(&si, 0xff, sizeof(si));
		si.dwReserved1=CAP_SECT_SIG;
		if(!FMDHOOK_WriteSector(startSectorAddr, v_CapBuf, &si, 1))
		{
			DEBUGMSG(1, (TEXT("!!! WriteSector:0x%x for cap Error !!!\r\n"), startSectorAddr));
			return FALSE;
		}
	}
	return TRUE;
}
